package com.sos
{
	import com.sos.core.DataObject;
	import com.sos.logging.Dumper;
	import com.sos.logging.IDumpable;
	import com.sos.utils.StringUtils;

	/**
	 * 
	 * @author luca tavecchia 
	 */	
	public class DebugOptions extends DataObject implements IDumpable
	{
		
		// -------------------------------------------------------------------------------
		// CONSTANTS
		// -------------------------------------------------------------------------------
		
		// Default values
		protected static const	DEFAULT_USER_ID:String						= "3";
		protected static const	DEFAULT_USER_USERNAME:String				= "CloudDancer";
		protected static const	DEFAULT_USER_PASSWORD:String				= "3333";
		
		// JSON Property names
		protected static const	JSON_PROPERTY_ENABLED:String				= "enabled";
		protected static const	JSON_PROPERTY_DEBUG_KEYS:String				= "keys";
		protected static const	JSON_PROPERTY_DEBUG_USER_ID:String			= "userID";
		protected static const	JSON_PROPERTY_DEBUG_USER_USERNAME:String	= "userUsername";
		protected static const	JSON_PROPERTY_DEBUG_USER_PASSWORD:String	= "userPassword";
		
		// Wildcard key used to enable ALL the keys
		public static const		ANY_DEBUG_KEY:String						= "<all>";
		
		// Default debug options
		public static const 	DEFAULT:DebugOptions = new DebugOptions(	{	enabled: 		true, 
																				userID: 		DEFAULT_USER_ID,
																				userUsername: 	DEFAULT_USER_USERNAME,
																				userPassword: 	DEFAULT_USER_PASSWORD,
																				keys: 			[	/* "comm.call", */
																									"sos.application", 
																							 		"core.game", 
																									"core.game.client.request",
																									"core.game.client.heartbeat",
																									"core.game.client.connection",
																									"core.game.engine.client",
																									"core.game.engine.timeout",
																									"core.game.engine.game",
																									"core.game.engine.matchmacking",
																									"comm.call.httpstatus"
																								] 
																			} );
		
		// -------------------------------------------------------------------------------
		// FIELDS
		// -------------------------------------------------------------------------------
		
		private var	_enabled:Boolean;
		private var	_keys:Vector.<String>;
		
		// Debug user data
		private var	_userID:String;
		private var	_userUsername:String;
		private var	_userPassword:String;

		// -------------------------------------------------------------------------------
		// CONSTRUCTOR
		// -------------------------------------------------------------------------------
		
		public function DebugOptions(data:Object = null)
		{
			// Init objects
			_keys = new Vector.<String>();
			// Clear data
			clear();
			// If data is provided, initializes the instance
			if (data != null) load(data);
		}
		
		override protected function validate(data:Object):void
		{
			if (!data.hasOwnProperty(JSON_PROPERTY_ENABLED)) 	throwLoadMissingPropError(JSON_PROPERTY_ENABLED);
			if (!data.hasOwnProperty(JSON_PROPERTY_DEBUG_KEYS)) throwLoadMissingPropError(JSON_PROPERTY_DEBUG_KEYS);
		}		
		
		override protected function fill(data:Object):void
		{
			// Enabling flag
			_enabled = Boolean(data[JSON_PROPERTY_ENABLED]);
			// Debug user data
			if (data.hasOwnProperty(JSON_PROPERTY_DEBUG_USER_ID)) 		_userID = data[JSON_PROPERTY_DEBUG_USER_ID];
			if (data.hasOwnProperty(JSON_PROPERTY_DEBUG_USER_USERNAME))	_userUsername = data[JSON_PROPERTY_DEBUG_USER_USERNAME];
			if (data.hasOwnProperty(JSON_PROPERTY_DEBUG_USER_PASSWORD))	_userPassword = data[JSON_PROPERTY_DEBUG_USER_PASSWORD];
			// Retrieve raw debug keys
			var raw_debug_keys:Array = data[JSON_PROPERTY_DEBUG_KEYS];
			// Clear current debug keys 
			clearDebugKeys();
			// Adds all the keys to the debug keys dictionary
			for (var i:int=0; i<raw_debug_keys.length; i++)
			{
				setDebugKey(raw_debug_keys[i]);
			}
		}
		
		// -------------------------------------------------------------------------------
		// PROPERTIES
		// -------------------------------------------------------------------------------
		
		public function get enabled():Boolean
		{
			return _enabled;
		}
		
		public function set enabled(value:Boolean):void
		{
			_enabled = value;
		}
		
		public function get userID():String
		{
			return _userID;
		}
		
		public function set userID(value:String):void
		{
			_userID = value;
		}
		
		public function get userUsername():String
		{
			return _userUsername;
		}
		
		public function set userUsername(value:String):void
		{
			_userUsername = value;
		}
		
		public function get userPassword():String
		{
			return _userPassword;
		}
		
		public function set userPassword(value:String):void
		{
			_userPassword = value;
		}
		
		public function get keys():Vector.<String>
		{
			return _keys;
		}
		
		// -------------------------------------------------------------------------------
		// PRIVATE METHODS
		// -------------------------------------------------------------------------------
		
		protected function catchAnyDebugKey():Boolean
		{
			return _keys.indexOf(ANY_DEBUG_KEY) >= 0;
		}
		
		protected function equalsDebugKeys(debugOptions:DebugOptions):Boolean
		{
			if (_keys.length != debugOptions.keys.length) return false;
			for (var i:int = 0; i<_keys.length; i++)
			{
				if (debugOptions.keys.indexOf(_keys[i]) < 0) return false;
			}
			return true;
		}
		
		protected function clearDebugKeys():void
		{
			_keys.splice(0, _keys.length);
		}
		
		// -------------------------------------------------------------------------------
		// PUBLIC METHODS
		// -------------------------------------------------------------------------------
		
		public function setDebugKey(debugKey:String):void
		{
			if (!hasDebugKey(debugKey))
			{
				_keys.push(debugKey);
			}
		}
		
		public function hasDebugKey(debugKey:String):Boolean
		{ 
			if (_keys.indexOf(debugKey) >= 0) return true;
			else
			{
				for (var i:int = 0; i < _keys.length; i++)
				{
					var key:String = _keys[i];
					if (StringUtils.endsWith(key, ".*"))
					{
						// Removes the wildcard
						key = key.substr(0, key.length - 2); 
						// If the current key represents the starting part of the key to serarch,
						// the current key is considered found
						if (debugKey.indexOf(key) == 0)
						{
							return true;
						}
					}
				}
			}
			return false;
		}
		
		public function canDebug(debugKey:String):Boolean
		{
			return	_enabled && (catchAnyDebugKey() || hasDebugKey(debugKey));
		}
		
		public function equals(debugOptions:DebugOptions):Boolean
		{
			if (this == debugOptions) return true;
			return	_enabled 		== debugOptions.enabled			&& 
					_userID 		== debugOptions.userID 			&&
					_userUsername 	== debugOptions.userUsername 	&& 
					_userPassword 	== debugOptions.userPassword 	&&
					equalsDebugKeys(debugOptions);
		}
		
		override public function clear():void
		{
			// application debug disabled
			_enabled = false;
			// Clear debug user data
			_userID 		= "";
			_userUsername	= "";
			_userPassword 	= "";
			// Clear debug keys
			clearDebugKeys();
		}
		
		public function dump(source:Array = null, indentDepth:int = 0):Array
		{
			return Dumper.dump(this, null, source, indentDepth);
		}
		
	}
}